<?php


namespace common\helpers;


class MyDocReader
{
    private $parameters;
    private $keyPattern = "[A-z0-9\_\-]+";
    private $endPattern = "[ ]*(?:@|\r\n|\n)";
    private static $p;

    private function MyDocReader()
    {
    }

    public static function getInstance()
    {
        if (self::$p == null) {
            self::$p = new MyDocReader();
        }
        return self::$p;
    }

    public function parsed($rawDocBlock)
    {
        $this->parameters = array();
        // Get all the lines and strip the * from the first character
        if (preg_match_all('#^\s*\*(.*)#m', $rawDocBlock, $lines) === false)
            return $this->parameters;
        $this->parseLines($lines[1]);
        $pattern = "/@(?=(.*)" . $this->endPattern . ")/U";
        preg_match_all($pattern, $rawDocBlock, $matches);
        foreach ($matches[1] as $rawParameter) {
            if (preg_match("/^(" . $this->keyPattern . ") (.*)$/", $rawParameter, $match)) {
                $parsedValue = $this->parseValue($match[2]);
                if (isset($this->parameters[$match[1]])) {
                    $this->parameters[$match[1]] = array_merge((array)$this->parameters[$match[1]], (array)$parsedValue);
                } else {
                    $this->parameters[$match[1]] = $parsedValue;
                }
            } else if (preg_match("/^" . $this->keyPattern . "$/", $rawParameter, $match)) {
                $this->parameters[$rawParameter] = TRUE;
            } else {
                $this->parameters[$rawParameter] = NULL;
            }
        }
        return $this->parameters;
    }

    private function parseValue($originalValue)
    {
        if ($originalValue && $originalValue !== 'null') {
            // try to json decode, if cannot then store as string
            if (($json = json_decode($originalValue, TRUE)) === NULL) {
                $value = $originalValue;
            } else {
                $value = $json;
            }
        } else {
            $value = NULL;
        }
        return $value;
    }

    private function parseLines($lines)
    {
        foreach ($lines as $line) {
            $parsedLine = $this->parseLine($line); // Parse the line
            if ($parsedLine === false && !isset($this->parameters['name'])) {
                if (isset($desc)) {
                    // Store the first line in the short description
                    $this->parameters['name'] = implode(PHP_EOL, $desc);
                }
                $desc = array();
            } elseif ($parsedLine !== false) {
                if (!preg_match("/@/", $parsedLine, $matches)) {
                    $desc[] = $parsedLine; // Store the line in the long description
                }
            }
        }
        $desc = implode(' ', $desc);
        if (!empty ($desc))
            $this->parameters['description'] = $desc;
    }

    private function parseLine($line)
    {
        // trim the whitespace from the line
        $line = trim($line);
        if (empty ($line))
            return false; // Empty line
        return $line;
    }

}